/*
 * libFuse.c
 *
 *  Created on: 18/04/2012
 *      Author: utnso
 */

#include "libFuse.h"

static struct fuse_operations ASLPC_operations = { .getattr = ASLPC_getattr, .mkdir = ASLPC_mkdir, .rmdir = ASLPC_rmdir, .ftruncate = ASLPC_ftruncate, .open = ASLPC_open, .read = ASLPC_read, .write = ASLPC_write, .release = ASLPC_release, .readdir = ASLPC_readdir, .create = ASLPC_create, .unlink = ASLPC_unlink};
static pthread_mutex_t mutexFinalizarPrograma;

void ejecutarFUSE(int32_t argc, char** argv) {
	pthread_mutex_lock(&mutexFinalizarPrograma);
	int32_t resultadoFUSE = 0;
	pthread_t tid = 0;
	argFUSE_t argFUSE;
	argFUSE.argc = argc;
	argFUSE.argv = (char**) malloc((argc + 1) * sizeof(char*));
	uint8_t i;
	for (i = 0; argv[i]; i++) {
		argFUSE.argv[i] = (char*) malloc(strlen(argv[i]) + 1);
		memset(argFUSE.argv[i], '\0', strlen(argv[i]) + 1);
		strcpy(argFUSE.argv[i], argv[i]);
	}
	argFUSE.argv[i] = NULL;
	argFUSE.argv = argv;
	argFUSE.res = &resultadoFUSE;
	pthread_create(&tid, NULL, (void*) &iniciarFUSE, (void*) &argFUSE);
	pthread_mutex_lock(&mutexFinalizarPrograma);
}

void iniciarFUSE(void* argFUSE) {
	printfCUCA("Se comienza a ejecutar FUSE\n");
	argFUSE_t* arg = (argFUSE_t*) argFUSE;
	*((*arg).res) = fuse_main((*arg).argc, (*arg).argv, &ASLPC_operations, NULL);
}

int32_t ASLPC_getattr(const char* path, struct stat* stbuf) {
	attrDirArch_t attr;
	int32_t res = obtenerAtributos((char*) path, &attr);
	stbuf->st_mode = (uint32_t) attr.modo; //TODO PREGUNTAR SI ES VALIDO EL CASTEO
	stbuf->st_size = (uint32_t) attr.size;
	return res;
}

int32_t ASLPC_mkdir(const char* path, mode_t modo) {
	return crearDirectorio((char*) path, modo);
}

int32_t ASLPC_rmdir(const char* path) {
	return borrarDirectorio((char*) path);
}

int32_t ASLPC_ftruncate(const char * path, off_t tamanio, struct fuse_file_info * info) {
	return truncar((char*) path, tamanio);
}

int32_t ASLPC_open(const char* path, struct fuse_file_info* fi) {
	return abrirArchivo((char*) path, fi->flags, "127.0.0.1");
}

int32_t ASLPC_read(const char* path, char* buf, size_t size, off_t offset, struct fuse_file_info* fi) {
	char *contenido;
	int32_t res = leerArchivo((char*) path, offset, size, &contenido);
	if (res > 0) {
		memcpy(buf, contenido, res);
	}
	return res;
}

int32_t ASLPC_write(const char* path, const char* buf, size_t size, off_t offset, struct fuse_file_info* fi) {
	return escribirArchivo((char*) path, size, offset, (char*) buf);
}

int32_t ASLPC_release(const char* path, struct fuse_file_info* info) {
	return cerrarArchivo((char*) path, info->flags, "127.0.0.1");
}

int32_t ASLPC_readdir(const char* path, void* buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info* fi) {
	nodoNombreDirOArch_t *pilaFte = NULL;
	int32_t res = leerDirectorio((char*) path, offset, &pilaFte);
	while (pilaFte != NULL) {
		char *bufferAux;
		desapilarNombreDirOArch(&pilaFte, &bufferAux);
		filler(buf, bufferAux, NULL, 0);
		free(bufferAux);
	}
	return res;
}

int32_t ASLPC_create(const char* path, mode_t modo, struct fuse_file_info* fInfo) {
	return crearArchivo((char*) path, modo);
}

int32_t ASLPC_unlink(const char* path) {
	return borrarArchivo((char*) path, "127.0.0.1");
}
